package guda.house.biz.impl;

import guda.grape.autogen.common.page.BizResult;
import guda.grape.util.Convert;
import guda.house.biz.ApiFeeBiz;
import guda.house.biz.beans.vo.PayDetail;
import guda.house.biz.beans.vo.PayDetailVO;
import guda.house.biz.query.*;
import guda.house.biz.util.PriceUtil;
import guda.house.biz.util.Transform;
import guda.house.biz.util.TransformHelper;
import guda.house.dal.dao.*;
import guda.house.dal.dataobject.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.util.StringUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created by well on 16/3/4.
 */
public class ApiFeeBizImpl implements ApiFeeBiz {

    @Autowired
    private SuiteOutUserRelDAO suiteOutUserRelDAO;
    @Autowired
    private BillEstateDAO billEstateDAO;
    @Autowired
    private BillElecDAO billElecDAO;
    @Autowired
    private BillWaterDAO billWaterDAO;
    @Autowired
    private BillParkingDAO billParkingDAO;
    @Autowired
    private SuiteDAO suiteDAO;
    @Autowired
    private UnitDAO unitDAO;
    @Autowired
    private BuildingDAO buildingDAO;
    @Autowired
    private VillageDAO villageDAO;
    @Autowired
    private OwnerDAO ownerDAO;
    @Autowired
    private BillPayDAO billPayDAO;
    @Autowired
    private BillExtDAO billExtDAO;
    @Autowired
    private TransactionTemplate transactionTemplate;


    @Override
    public BizResult queryUnpayFee(ApiFeeQuery apiFeeQuery) {
        BizResult bizResult = new BizResult();
        Date start = null;
        Date end = null;
        if(StringUtils.hasText(apiFeeQuery.getStartDate())&& StringUtils.hasText(apiFeeQuery.getEndDate())){
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
            try {
               start =  simpleDateFormat.parse(apiFeeQuery.getStartDate());
            } catch (ParseException e) {
            }
            simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
            try {
                end =  simpleDateFormat.parse(apiFeeQuery.getEndDate());
            } catch (ParseException e) {
            }
        }
        List<SuiteOutUserRelDO> byOutUserId = suiteOutUserRelDAO.getByOutUserId(apiFeeQuery.getOutUserId());
        if(byOutUserId.size() == 0){
            bizResult.success=true;
            return bizResult;
        }
        Long suiteId = byOutUserId.get(0).getSuiteId();
        List<BillElecDO> billElecDOList = new ArrayList<BillElecDO>();
        List<BillWaterDO> billWaterDOList = new ArrayList<BillWaterDO>();
        List<BillEstateDO> billEstateDOList = new ArrayList<BillEstateDO>();
        List<BillParkingDO> billParkingDOList = new ArrayList<BillParkingDO>();
        if("water".equals(apiFeeQuery.getFeeType())){
            BillWaterQuery billWaterQuery = new BillWaterQuery();
            billWaterQuery.setPageSize(500);
            billWaterQuery.setSuiteId(suiteId);
            billWaterQuery.setEndDate(end);
            billWaterQuery.setStartDate(start);
             billWaterDOList = billWaterDAO.selectForUnpay(billWaterQuery);

        }else if("elec".equals(apiFeeQuery.getFeeType())){
            BillElecQuery billElecQuery = new BillElecQuery();
            billElecQuery.setPageSize(500);
            billElecQuery.setSuiteId(suiteId);
            billElecQuery.setEndDate(end);
            billElecQuery.setStartDate(start);
             billElecDOList = billElecDAO.selectForUnpay(billElecQuery);

        }else if("estate".equals(apiFeeQuery.getFeeType())){
            BillEstateQuery billEstateQuery = new BillEstateQuery();
            billEstateQuery.setPageSize(500);
            billEstateQuery.setSuiteId(suiteId);
            billEstateQuery.setEndDate(end);
            billEstateQuery.setStartDate(start);
             billEstateDOList = billEstateDAO.selectForUnpay(billEstateQuery);

        }else if("parking".equals(apiFeeQuery.getFeeType())){
            BillParkingQuery billParkingQuery = new BillParkingQuery();
            billParkingQuery.setPageSize(500);
            billParkingQuery.setSuiteId(suiteId);
            billParkingQuery.setEndDate(end);
            billParkingQuery.setStartDate(start);
             billParkingDOList = billParkingDAO.selectForUnpay(billParkingQuery);
        }else{

            BillParkingQuery billParkingQuery = new BillParkingQuery();
            billParkingQuery.setPageSize(500);
            billParkingQuery.setSuiteId(suiteId);
            billParkingQuery.setEndDate(end);
            billParkingQuery.setStartDate(start);
             billParkingDOList = billParkingDAO.selectForUnpay(billParkingQuery);

            BillEstateQuery billEstateQuery = new BillEstateQuery();
            billEstateQuery.setPageSize(500);
            billEstateQuery.setSuiteId(suiteId);
            billEstateQuery.setEndDate(end);
            billEstateQuery.setStartDate(start);
            billEstateDOList = billEstateDAO.selectForUnpay(billEstateQuery);

            BillWaterQuery billWaterQuery = new BillWaterQuery();
            billWaterQuery.setPageSize(500);
            billWaterQuery.setSuiteId(suiteId);
            billWaterQuery.setEndDate(end);
            billWaterQuery.setStartDate(start);
             billWaterDOList = billWaterDAO.selectForUnpay(billWaterQuery);

            BillElecQuery billElecQuery = new BillElecQuery();
            billElecQuery.setPageSize(500);
            billElecQuery.setSuiteId(suiteId);
            billElecQuery.setEndDate(end);
            billElecQuery.setStartDate(start);
             billElecDOList = billElecDAO.selectForUnpay(billElecQuery);

        }

        long allTotal = 0L;
        PayDetailVO payDetailVO = new PayDetailVO();
        List<PayDetail> payDetailList = new ArrayList<PayDetail>();
        payDetailVO.setPayDetailList(payDetailList);
        if(billEstateDOList.size()>0){
            Collections.sort(billEstateDOList, new Comparator<BillEstateDO>() {
                @Override
                public int compare(BillEstateDO o1, BillEstateDO o2) {
                    return o2.getGmtStart().compareTo(o1.getGmtStart());
                }
            });
            BillEstateDO billEstateDO = billEstateDOList.get(0);
            if(payDetailVO.getVillageDO() == null) {
                SuiteDO suiteById = suiteDAO.getSuiteById(billEstateDO.getSuiteId());
                payDetailVO.setSuiteDO(suiteById);
                UnitDO unitById = unitDAO.getUnitById(suiteById.getUnitId());
                payDetailVO.setUnitDO(unitById);
                BuildingDO buildingById = buildingDAO.getBuildingById(unitById.getBuildingId());
                payDetailVO.setBuildingDO(buildingById);
                payDetailVO.setVillageDO(villageDAO.getVillageById(buildingById.getVillageId()));
                OwnerQuery ownerQuery = new OwnerQuery();
                ownerQuery.setSuiteId(suiteById.getSuiteId());
                List<OwnerDO> ownerDOs = ownerDAO.selectForPage(ownerQuery);
                payDetailVO.setOwnerDOList(ownerDOs);
                payDetailVO.setGmt(billEstateDO.getGmtCreate());
            }
            PayDetail payDetail = new PayDetail();
            payDetail.setFeeName("物业费");
            payDetail.setStart(billEstateDOList.get(billEstateDOList.size() - 1).getGmtStart());
            payDetail.setEnd(billEstateDOList.get(0).getGmtEnd());

            List<String> billId = TransformHelper.transform(billEstateDOList, new Transform<BillEstateDO, String>() {
                @Override
                public String transform(BillEstateDO object) {
                    return "estate_"+object.getBillId();
                }
            });
            payDetail.setBillIdList(billId);

            long c = 0L;
            for (BillEstateDO billEstateDO1 : billEstateDOList) {
                c = c + billEstateDO1.getPayTotal();
            }
            payDetail.setPayTotal(c);
            payDetailList.add(payDetail);
            allTotal = allTotal + payDetail.getPayTotal();
        }

        if(billWaterDOList.size()>0){
            Collections.sort(billWaterDOList, new Comparator<BillWaterDO>() {
                @Override
                public int compare(BillWaterDO o1, BillWaterDO o2) {
                    return o2.getGmtStart().compareTo(o1.getGmtStart());
                }
            });
            BillWaterDO billWaterDO = billWaterDOList.get(0);
            if(payDetailVO.getVillageDO() == null) {
                SuiteDO suiteById = suiteDAO.getSuiteById(billWaterDO.getSuiteId());
                payDetailVO.setSuiteDO(suiteById);
                UnitDO unitById = unitDAO.getUnitById(suiteById.getUnitId());
                payDetailVO.setUnitDO(unitById);
                BuildingDO buildingById = buildingDAO.getBuildingById(unitById.getBuildingId());
                payDetailVO.setBuildingDO(buildingById);
                payDetailVO.setVillageDO(villageDAO.getVillageById(buildingById.getVillageId()));
                OwnerQuery ownerQuery = new OwnerQuery();
                ownerQuery.setSuiteId(suiteById.getSuiteId());
                List<OwnerDO> ownerDOs = ownerDAO.selectForPage(ownerQuery);
                payDetailVO.setOwnerDOList(ownerDOs);
                payDetailVO.setGmt(billWaterDO.getGmtCreate());
            }
            PayDetail payDetail = new PayDetail();
            payDetail.setFeeName("水费");
            payDetail.setStart(billWaterDOList.get(billWaterDOList.size() - 1).getGmtStart());
            payDetail.setEnd(billWaterDOList.get(0).getGmtEnd());


            List<String> billId = TransformHelper.transform(billWaterDOList, new Transform<BillWaterDO, String>() {
                @Override
                public String transform(BillWaterDO object) {
                    return "water_"+object.getBillId();
                }
            });
            payDetail.setBillIdList(billId);

            long c = 0L;
            for (BillWaterDO billWaterDO1 : billWaterDOList) {
                c = c + billWaterDO1.getPayTotal();
            }
            payDetail.setPayTotal(c);
            payDetailList.add(payDetail);
            allTotal = allTotal + payDetail.getPayTotal();
        }

        if(billElecDOList.size()>0){
            Collections.sort(billElecDOList, new Comparator<BillElecDO>() {
                @Override
                public int compare(BillElecDO o1, BillElecDO o2) {
                    return o2.getGmtStart().compareTo(o1.getGmtStart());
                }
            });
            BillElecDO billElecDO = billElecDOList.get(0);
            if(payDetailVO.getVillageDO() == null) {
                SuiteDO suiteById = suiteDAO.getSuiteById(billElecDO.getSuiteId());
                payDetailVO.setSuiteDO(suiteById);
                UnitDO unitById = unitDAO.getUnitById(suiteById.getUnitId());
                payDetailVO.setUnitDO(unitById);
                BuildingDO buildingById = buildingDAO.getBuildingById(unitById.getBuildingId());
                payDetailVO.setBuildingDO(buildingById);
                payDetailVO.setVillageDO(villageDAO.getVillageById(buildingById.getVillageId()));
                OwnerQuery ownerQuery = new OwnerQuery();
                ownerQuery.setSuiteId(suiteById.getSuiteId());
                List<OwnerDO> ownerDOs = ownerDAO.selectForPage(ownerQuery);
                payDetailVO.setOwnerDOList(ownerDOs);
                payDetailVO.setGmt(billElecDO.getGmtCreate());
            }
            PayDetail payDetail = new PayDetail();
            payDetail.setFeeName("电费");

            payDetail.setStart(billElecDOList.get(billElecDOList.size() - 1).getGmtStart());
            payDetail.setEnd(billElecDOList.get(0).getGmtEnd());


            List<String> billId = TransformHelper.transform(billElecDOList, new Transform<BillElecDO, String>() {
                @Override
                public String transform(BillElecDO object) {
                    return "elec_"+ object.getBillId();
                }
            });
            payDetail.setBillIdList(billId);

            long c = 0L;
            for (BillElecDO billElecDO1 : billElecDOList) {
                c = c + billElecDO1.getPayTotal();
            }
            payDetail.setPayTotal(c);
            payDetailList.add(payDetail);
            allTotal = allTotal + payDetail.getPayTotal();
        }
        if (billParkingDOList.size() > 0) {
            Collections.sort(billParkingDOList, new Comparator<BillParkingDO>() {
                @Override
                public int compare(BillParkingDO o1, BillParkingDO o2) {
                    return o2.getGmtStart().compareTo(o1.getGmtStart());
                }
            });
            BillParkingDO billParkingDO = billParkingDOList.get(0);
            if(payDetailVO.getVillageDO() == null) {
                SuiteDO suiteById = suiteDAO.getSuiteById(billParkingDO.getSuiteId());
                payDetailVO.setSuiteDO(suiteById);
                UnitDO unitById = unitDAO.getUnitById(suiteById.getUnitId());
                payDetailVO.setUnitDO(unitById);
                BuildingDO buildingById = buildingDAO.getBuildingById(unitById.getBuildingId());
                payDetailVO.setBuildingDO(buildingById);
                payDetailVO.setVillageDO(villageDAO.getVillageById(buildingById.getVillageId()));
                OwnerQuery ownerQuery = new OwnerQuery();
                ownerQuery.setSuiteId(suiteById.getSuiteId());
                List<OwnerDO> ownerDOs = ownerDAO.selectForPage(ownerQuery);
                payDetailVO.setOwnerDOList(ownerDOs);
                payDetailVO.setGmt(billParkingDO.getGmtCreate());
            }

            PayDetail payDetail = new PayDetail();
            payDetail.setFeeName("车位费");
            payDetail.setStart(billParkingDOList.get(billParkingDOList.size() - 1).getGmtStart());
            payDetail.setEnd(billParkingDOList.get(0).getGmtEnd());

            List<String> billId = TransformHelper.transform(billParkingDOList, new Transform<BillParkingDO, String>() {
                @Override
                public String transform(BillParkingDO object) {
                    return "parking_"+object.getBillId();
                }
            });
            payDetail.setBillIdList(billId);

            long c = 0L;
            for (BillParkingDO billParkingDO1 : billParkingDOList) {
                c = c + billParkingDO1.getPayTotal();
            }
            payDetail.setPayTotal(c);
            payDetailList.add(payDetail);
            allTotal = allTotal + payDetail.getPayTotal();

        }
        payDetailVO.setPayTotal(allTotal);
        payDetailVO.setPayTotalCN(PriceUtil.toRMB(allTotal));
        bizResult.data.put("payDetailVO",payDetailVO);
        bizResult.success=true;
        return bizResult;
    }

    @Override
    public BizResult queryPaiedFee(ApiFeeQuery apiFeeQuery) {
        BizResult bizResult = new BizResult();
        List<SuiteOutUserRelDO> byOutUserId = suiteOutUserRelDAO.getByOutUserId(apiFeeQuery.getOutUserId());
        if(byOutUserId.size() == 0){
            bizResult.success=true;
            return bizResult;
        }
        Date start = null;
        Date end = null;
        if(StringUtils.hasText(apiFeeQuery.getStartDate())&& StringUtils.hasText(apiFeeQuery.getEndDate())){
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
            try {
                start =  simpleDateFormat.parse(apiFeeQuery.getStartDate());
            } catch (ParseException e) {
            }
            simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
            try {
                end =  simpleDateFormat.parse(apiFeeQuery.getEndDate());
            } catch (ParseException e) {
            }
        }
        final Long suiteId = byOutUserId.get(0).getSuiteId();
        BillPayQuery billPayQuery = new BillPayQuery();
        billPayQuery.setSuiteId(suiteId);
        billPayQuery.setStartDate(start);
        billPayQuery.setEndDate(end);
        billPayQuery.setPageNo(apiFeeQuery.getPageNo());
        billPayQuery.setPageSize(apiFeeQuery.getPageSize());
        List<BillPayDO> billPayList = billPayDAO.selectForPayedLog(billPayQuery);
        int totalCount = billPayDAO.countForPayedLog(billPayQuery);
        billPayQuery.setTotalCount(totalCount);
        bizResult.data.put("billPayList", billPayList);
        bizResult.data.put("query", billPayQuery);
        bizResult.success = true;
        return bizResult;
    }

    @Override
    public BizResult pay(final String outUserId,final String billPayId) {
        final BizResult bizResult = new BizResult();
        if(billPayId == null){
            return bizResult;
        }
        List<SuiteOutUserRelDO> byOutUserId = suiteOutUserRelDAO.getByOutUserId(outUserId);
        if(byOutUserId.size() == 0){
            bizResult.success=true;
            return bizResult;
        }
        final Long suiteId = byOutUserId.get(0).getSuiteId();
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
                long total = 0;
                String[] billIdList = billPayId.split(",");
                StringBuilder buf = new StringBuilder();
                for (String billId : billIdList) {
                    String[] split = billId.split("_");
                    if ("parking".equals(split[0])) {
                        BillParkingDO billParkingById = billParkingDAO.getBillParkingById(Convert.toLong(split[1]));
                        if(billParkingById.getSuiteId().longValue()!=suiteId.longValue()){
                            throw new RuntimeException("非法支付");
                        }
                        total = total + billParkingById.getPayTotal();
                        buf.append("车位费（").append(billParkingById.getRecordYear())
                                .append("年").append(billParkingById.getRecordMonth()).append("月）：").append(PriceUtil.formatCNY(billParkingById.getPayTotal())).append("元;");
                    } else if ("estate".equals(split[0])) {
                        BillEstateDO billEstateById = billEstateDAO.getBillEstateById(Convert.toLong(split[1]));
                        if(billEstateById.getSuiteId().longValue()!=suiteId.longValue()){
                            throw new RuntimeException("非法支付");
                        }
                        total = total + billEstateById.getPayTotal();
                        buf.append("物业费（").append(billEstateById.getRecordYear())
                                .append("年").append(billEstateById.getRecordMonth()).append("月）：").append(PriceUtil.formatCNY(billEstateById.getPayTotal())).append("元;");
                    } else if ("water".equals(split[0])) {
                        BillWaterDO billWaterById = billWaterDAO.getBillWaterById(Convert.toLong(split[1]));
                        if(billWaterById.getSuiteId().longValue()!=suiteId.longValue()){
                            throw new RuntimeException("非法支付");
                        }
                        total = total + billWaterById.getPayTotal();
                        buf.append("水费（").append(billWaterById.getRecordYear())
                                .append("年").append(billWaterById.getRecordMonth()).append("月）：").append(PriceUtil.formatCNY(billWaterById.getPayTotal())).append("元;");
                    } else if ("elec".equals(split[0])) {
                        BillElecDO billElecById = billElecDAO.getBillElecById(Convert.toLong(split[1]));
                        if(billElecById.getSuiteId().longValue()!=suiteId.longValue()){
                            throw new RuntimeException("非法支付");
                        }
                        total = total + billElecById.getPayTotal();
                        buf.append("电费（").append(billElecById.getRecordYear())
                                .append("年").append(billElecById.getRecordMonth()).append("月）：").append(PriceUtil.formatCNY(billElecById.getPayTotal())).append("元;");
                    } else if ("deposit".equals(split[0])) {
                        BillExtDO billExtById = billExtDAO.getBillExtById(Convert.toLong(split[1]));
                        total = total + billExtById.getPayTotal();
                        buf.append("押金:").append(PriceUtil.formatCNY(billExtById.getPayTotal())).append("元;");
                    } else if ("other".equals(split[0])) {
                        BillExtDO billExtById = billExtDAO.getBillExtById(Convert.toLong(split[1]));
                        total = total + billExtById.getPayTotal();
                        buf.append("其他费用:").append(PriceUtil.formatCNY(billExtById.getPayTotal())).append("元;");
                    }
                }

                BillPayDO billPayDO = new BillPayDO();
                billPayDO.setSuiteId(suiteId);
                billPayDO.setPayTypeId(0L);
                billPayDO.setPayTotal(total);
                billPayDO.setPayDesc(buf.toString());
                billPayDO.setPayTotalCharge(0L);

                billPayDO.setPayType("网上支付");
                Long payId = billPayDAO.insert(billPayDO);
                bizResult.data.put("payId",payId);


                for (String billId : billIdList) {
                    String[] split = billId.split("_");
                    if ("parking".equals(split[0])) {
                        BillParkingDO billParkingById = billParkingDAO.getBillParkingById(Convert.toLong(split[1]));
                        billParkingById.setIsPayed(1);
                        billParkingById.setGmtPay(new Date());
                        billParkingById.setBillPayId(payId);
                        billParkingDAO.updateByIdSelective(billParkingById);
                    } else if ("estate".equals(split[0])) {
                        BillEstateDO billEstateById = billEstateDAO.getBillEstateById(Convert.toLong(split[1]));
                        billEstateById.setIsPayed(1);
                        billEstateById.setGmtPay(new Date());
                        billEstateById.setBillPayId(payId);
                        billEstateDAO.updateByIdSelective(billEstateById);
                    } else if ("water".equals(split[0])) {

                        BillWaterDO billWaterById = billWaterDAO.getBillWaterById(Convert.toLong(split[1]));
                        billWaterById.setIsPayed(1);
                        billWaterById.setGmtPay(new Date());
                        billWaterById.setBillPayId(payId);
                        billWaterDAO.updateByIdSelective(billWaterById);
                    } else if ("elec".equals(split[0])) {
                        BillElecDO billElecById = billElecDAO.getBillElecById(Convert.toLong(split[1]));
                        billElecById.setIsPayed(1);
                        billElecById.setGmtPay(new Date());
                        billElecById.setBillPayId(payId);
                        billElecDAO.updateByIdSelective(billElecById);
                    } else if ("deposit".equals(split[0])) {
                        BillExtDO billExtById = billExtDAO.getBillExtById(Convert.toLong(split[1]));
                        billExtById.setIsPayed(1);
                        billExtById.setBillPayId(payId);
                        billExtDAO.updateByIdSelective(billExtById);
                    } else if ("other".equals(split[0])) {
                        BillExtDO billExtById = billExtDAO.getBillExtById(Convert.toLong(split[1]));
                        billExtById.setIsPayed(1);
                        billExtById.setBillPayId(payId);
                        billExtDAO.updateByIdSelective(billExtById);
                    }
                }
                bizResult.success=true;
            }
        });


        return bizResult;
    }
}
